package com.ce.wnd;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;

import com.ce.socket.ABalance;
import com.ce.socket.ASocketPool;
import com.ce.socket.BSocketPool;
import com.ce.socket.CBalance;
import com.ce.socket.CSocket;
import com.ce.socket.CSocketPool;
import com.ce.socket.DalSocket;
import com.ce.socket.DalSocketPool;
import com.ce.socket.IBalance;
import com.ce.socket.ISocketPool;
import com.ce.socket.SendByBalanceCallable;
import com.ce.socket.SendByPoolCallable;
import com.ce.socket.SendCallable;
import com.ce.socket.SendRunnable;
import com.ce.study.procum.Consumer;
import com.ce.study.procum.ConsumerRunnable;
import com.ce.study.procum.ExecImmediatelyRunnable;
import com.ce.study.procum.GoodsStock;
import com.ce.study.procum.ProducterTh;
import com.ce.study.socketpool.CM20JAVA;
import com.ce.study.socketpool.SockIOPool;
import com.ce.study.socketpool.SockIOPool.SockIO;

public class TestStudyWnd extends Composite {
	private Text txtExecTimes;
	private Text txtThreadCount;
	private GoodsStock goodsStock = new GoodsStock();
	private SockIOPool pool = null;
	private DalSocketPool dalSocketPool = null;
	private ISocketPool socketPool = null;
	private IBalance balance = null;
	private Consumer consumer;
	private ProducterTh producter;
	private ExecutorService executorService;
	private int corePoolSize = 5;
	private int maximumPoolSize = 50;
	private int keepAliveTime = 15;
	private TimeUnit unit = TimeUnit.SECONDS;
	private BlockingQueue<Runnable> workQueue;
	private int queueSize = 5;
	public TestStudyWnd(Composite parent, int style) {
		super(parent, style);

		final Button btnPro1 = new Button(this, SWT.NONE);
		btnPro1.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				goodsStock.addGoods("1-"+System.currentTimeMillis());
			}
		});
		btnPro1.setText("product1");
		btnPro1.setBounds(10, 10, 70, 22);

		final Button btnPro2 = new Button(this, SWT.NONE);
		btnPro2.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				goodsStock.addGoods("2-"+System.currentTimeMillis());
			}
		});
		btnPro2.setText("product2");
		btnPro2.setBounds(10, 38, 70, 22);

		final Button btnStart = new Button(this, SWT.NONE);
		btnStart.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initProCum();
			}
		});
		btnStart.setText("start");
		btnStart.setBounds(10, 66, 70, 22);

		final Button btnInitSyn = new Button(this, SWT.NONE);
		btnInitSyn.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initSynchronousQueue();
			}
		});
		btnInitSyn.setText("initSyn");
		btnInitSyn.setBounds(95, 10, 70, 22);

		final Button btnAddWait = new Button(this, SWT.NONE);
		btnAddWait.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				executorService.execute(new ConsumerRunnable(goodsStock,"add"+System.currentTimeMillis()));
			}
		});
		btnAddWait.setText("addWait");
		btnAddWait.setBounds(95, 38, 70, 22);

		final Button btnAddImd = new Button(this, SWT.NONE);
		btnAddImd.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				executorService.execute(new ExecImmediatelyRunnable());
			}
		});
		btnAddImd.setText("addImd");
		btnAddImd.setBounds(95, 66, 70, 22);

		final Button btnInitLink = new Button(this, SWT.NONE);
		btnInitLink.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initLinkedBlockingQueue();
			}
		});
		btnInitLink.setText("initLink");
		btnInitLink.setBounds(180, 10, 70, 22);

		final Button btnInitArray = new Button(this, SWT.NONE);
		btnInitArray.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initArrayBlockingQueue();
			}
		});
		btnInitArray.setText("initArray");
		btnInitArray.setBounds(265, 10, 70, 22);

		final Button btnInitPool = new Button(this, SWT.NONE);
		btnInitPool.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				initPool();
			}
		});
		btnInitPool.setText("initPool");
		btnInitPool.setBounds(10, 123, 70, 22);

		final Button btnSendData = new Button(this, SWT.NONE);
		btnSendData.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				sendData();
			}
		});
		btnSendData.setText("send");
		btnSendData.setBounds(10, 151, 70, 22);

		final Button btnMyInitPool = new Button(this, SWT.NONE);
		btnMyInitPool.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				initDalPool();
			}
		});
		btnMyInitPool.setText("initMy");
		btnMyInitPool.setBounds(95, 123, 70, 22);

		final Button btnMySend = new Button(this, SWT.NONE);
		btnMySend.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				sendDalData();
			}
		});
		btnMySend.setText("send");
		btnMySend.setBounds(95, 151, 70, 22);

		final Button btnMutil = new Button(this, SWT.NONE);
		btnMutil.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				sendThread();
			}
		});
		btnMutil.setText("thread");
		btnMutil.setBounds(95, 179, 70, 22);

		final Button btnTotal = new Button(this, SWT.NONE);
		btnTotal.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				for ( Iterator<DalSocket> j = dalSocketPool.totalPool.keySet().iterator(); j.hasNext(); ) {
					DalSocket socket = j.next();
					System.out.println(socket.toString());
				}
			}
		});
		btnTotal.setText("total");
		btnTotal.setBounds(95, 207, 70, 22);

		final Button btnCheck = new Button(this, SWT.NONE);
		btnCheck.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				checkPool();
			}
		});
		btnCheck.setText("check");
		btnCheck.setBounds(95, 235, 70, 22);

		final Button btnCall = new Button(this, SWT.NONE);
		btnCall.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				callAndGetResult();
			}
		});
		btnCall.setText("SynCall");
		btnCall.setBounds(95, 263, 70, 22);

		final Button btnMyInitA = new Button(this, SWT.NONE);
		btnMyInitA.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initASocketPool();
			}
		});
		btnMyInitA.setText("initA");
		btnMyInitA.setBounds(180, 123, 70, 22);

		final Button btnCallASocket = new Button(this, SWT.NONE);
		btnCallASocket.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				callSocketAndGetResult();
			}
		});
		btnCallASocket.setText("TASocket");
		btnCallASocket.setBounds(180, 151, 70, 22);

		final Button btnMyInitB = new Button(this, SWT.NONE);
		btnMyInitB.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initBSocketPool();
			}
		});
		btnMyInitB.setText("initB");
		btnMyInitB.setBounds(180, 179, 70, 22);

		final Button btnCallBSocket = new Button(this, SWT.NONE);
		btnCallBSocket.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				callSocketAndGetResult();
			}
		});
		btnCallBSocket.setText("TBSocket");
		btnCallBSocket.setBounds(180, 207, 70, 22);

		txtThreadCount = new Text(this, SWT.BORDER);
		txtThreadCount.setText("30");
		txtThreadCount.setBounds(10, 92, 80, 25);

		txtExecTimes = new Text(this, SWT.BORDER);
		txtExecTimes.setText("1000");
		txtExecTimes.setBounds(95, 92, 80, 25);

		final Button btnMyInitC = new Button(this, SWT.NONE);
		btnMyInitC.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initCSocketPool();
			}
		});
		btnMyInitC.setText("initC");
		btnMyInitC.setBounds(180, 235, 70, 22);

		final Button btnCallCSocket = new Button(this, SWT.NONE);
		btnCallCSocket.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				callSocketAndGetResult();
			}
		});
		btnCallCSocket.setText("TCSocket");
		btnCallCSocket.setBounds(180, 263, 70, 22);

		final Button btnInitABalance = new Button(this, SWT.NONE);
		btnInitABalance.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				initABalance();
			}
		});
		btnInitABalance.setText("initABalance");
		btnInitABalance.setBounds(265, 123, 70, 22);

		final Button btnCallABalance = new Button(this, SWT.NONE);
		btnCallABalance.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				callBalanceAndGetResult();
			}
		});
		btnCallABalance.setText("TABalance");
		btnCallABalance.setBounds(265, 151, 70, 22);

		final Button btnInitCBalance = new Button(this, SWT.NONE);
		btnInitCBalance.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				initCBalance();
			}
		});
		btnInitCBalance.setText("initCBalance");
		btnInitCBalance.setBounds(265, 179, 70, 22);

		final Button btnCallCBalance = new Button(this, SWT.NONE);
		btnCallCBalance.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent selectionevent) {
				callBalanceAndGetResult();
			}
		});
		btnCallCBalance.setText("TCBalance");
		btnCallCBalance.setBounds(265, 207, 70, 22);
	}
	private void initCBalance() {
		try {
			balance = new CBalance();
			balance.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initABalance() {
		try {
			String[] servers = new String[] {"127.0.0.1:8020","127.0.0.1:8030"};
			Integer[] weights = new Integer[] {2,1};
			balance = new ABalance(servers, weights, CSocketPool.class, CSocket.class);
			balance.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initCSocketPool() {
		try {
			socketPool = new CSocketPool("127.0.0.1:8020", CSocket.class);
			socketPool.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initBSocketPool() {
		try {
			socketPool = new BSocketPool("127.0.0.1:8020");
			socketPool.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initASocketPool() {
		try {
			socketPool = new ASocketPool("127.0.0.1:8020");
			socketPool.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void callBalanceAndGetResult() {
		try {
			final long begin = System.currentTimeMillis();
			final ArrayList<Future<String>> results = new ArrayList<Future<String>>();
			for (int i = 0; i < Integer.parseInt(txtThreadCount.getText()); i++) {   
			    results.add(executorService.submit(new SendByBalanceCallable(balance,Integer.parseInt(txtExecTimes.getText()))));   
			}
			Thread monitor = new Thread(){
				@Override
				public void run() {
					while(true) {
						try {
							boolean isAllFinishec = true;
							for (Future<String> fs : results) {   
								isAllFinishec = isAllFinishec && fs.isDone();
							}
							if(isAllFinishec) {
								for (Future<String> fs : results) { 
									System.out.println(fs.get());
								}
								break;
							}
							sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						} catch (ExecutionException e) {
							e.printStackTrace();
						} 
					}
					long space = System.currentTimeMillis() - begin;
					System.out.println("total time:"+space+"ms");
				}
			};
			monitor.start();
			//executorService.shutdown(); 
		} catch (Exception e) {
			e.printStackTrace();
		}  
	}
	private void callSocketAndGetResult() {
		try {
			final long begin = System.currentTimeMillis();
			final ArrayList<Future<String>> results = new ArrayList<Future<String>>();
			for (int i = 0; i < Integer.parseInt(txtThreadCount.getText()); i++) {   
			    results.add(executorService.submit(new SendByPoolCallable(socketPool,Integer.parseInt(txtExecTimes.getText()))));   
			}
			Thread monitor = new Thread(){
				@Override
				public void run() {
					while(true) {
						try {
							boolean isAllFinishec = true;
							for (Future<String> fs : results) {   
								isAllFinishec = isAllFinishec && fs.isDone();
							}
							if(isAllFinishec) {
								for (Future<String> fs : results) { 
									System.out.println(fs.get());
								}
								break;
							}
							sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						} catch (ExecutionException e) {
							e.printStackTrace();
						} 
					}
					long space = System.currentTimeMillis() - begin;
					System.out.println("total time:"+space+"ms");
				}
			};
			monitor.start();
			//executorService.shutdown(); 
		} catch (Exception e) {
			e.printStackTrace();
		}  
	}
	private void callAndGetResult() {
		try {
			
			final ArrayList<Future<String>> results = new ArrayList<Future<String>>();
			for (int i = 0; i < Integer.parseInt(txtThreadCount.getText()); i++) {   
			    results.add(executorService.submit(new SendCallable(dalSocketPool,Integer.parseInt(txtExecTimes.getText()))));   
			}
			Thread monitor = new Thread(){
				@Override
				public void run() {
					while(true) {
						try {
							boolean isAllFinishec = true;
							for (Future<String> fs : results) {   
								isAllFinishec = isAllFinishec && fs.isDone();
							}
							if(isAllFinishec) {
								for (Future<String> fs : results) { 
									System.out.println(fs.get());
								}
								break;
							}
							sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						} catch (ExecutionException e) {
							e.printStackTrace();
						} 
					}
				}
			};
			monitor.start();
			//executorService.shutdown(); 
		} catch (Exception e) {
			e.printStackTrace();
		}  
	}
	private void checkPool() {
		try {
			//dalSocketPool.selfMaint();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void sendThread() {
		try {
			executorService.execute(new SendRunnable(dalSocketPool));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initDalPool() {
		try {
			dalSocketPool = new DalSocketPool("127.0.0.1:8020");
			dalSocketPool.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void sendDalData() {
		try {
			Map<String,String> mbody = new HashMap<String, String>();
			mbody.put("URI", "/dal/testnoauth/fcode.xml");
			mbody.put("METHOD", "GET");
			
			CM20JAVA reqmsg = new CM20JAVA(mbody);
			reqmsg.encode();
			reqmsg.printMessage();

			byte[] rep = dalSocketPool.sendData(reqmsg.getMessage(), 3);

			CM20JAVA repmsg = new CM20JAVA(Map.class);
			repmsg.decode(rep);
			repmsg.printMessage();
			Object repObj = repmsg.getBodyObject();
			System.out.println(repObj);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initPool() {
		try {
			pool = new SockIOPool();
			pool.setServer("127.0.0.1:8020");
			pool.initialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void sendData() {
		try {
			Map<String,String> mbody = new HashMap<String, String>();
			mbody.put("URI", "/dal/testnoauth/fcode.xml");
			mbody.put("METHOD", "GET");
			
			CM20JAVA reqmsg = new CM20JAVA(mbody);
			reqmsg.encode();
			reqmsg.printMessage();

			SockIO sockIO = pool.getConnection();
			//sockIO.write(reqmsg.getMessage());
			sockIO.write(new String("CM20NULL00GB00000020").getBytes());
			sockIO.flush();
//			ByteBuffer newBuf = ByteBuffer.allocate( 128 );
//			int count = sockIO.getChannel().read(newBuf);
//			System.out.println(count);
//			byte[] rep = newBuf.array();
			byte[] rep = sockIO.read();
			CM20JAVA repmsg = new CM20JAVA(Map.class);
			repmsg.decode(rep);
			repmsg.printMessage();
			Object repObj = repmsg.getBodyObject();
			System.out.println(repObj);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private void initProCum() {
		consumer = new Consumer(goodsStock,"consumer");
		consumer.start();
		producter = new ProducterTh(goodsStock,"producterTh");
		producter.start();
	}
	
	private void initSynchronousQueue() {
		try {
			if(workQueue == null)
				workQueue = new SynchronousQueue<Runnable>();
			executorService = new ThreadPoolExecutor(
					corePoolSize, 
					maximumPoolSize,
					keepAliveTime, 
					unit, 
					workQueue
					);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	private void initLinkedBlockingQueue() {
		try {
			if(workQueue == null)
				workQueue = new LinkedBlockingQueue<Runnable>();
			executorService = new ThreadPoolExecutor(
					corePoolSize, 
					maximumPoolSize,
					keepAliveTime, 
					unit, 
					workQueue
					);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	private void initArrayBlockingQueue() {
		try {
			if(workQueue == null)
				workQueue = new ArrayBlockingQueue<Runnable>(queueSize);
			executorService = new ThreadPoolExecutor(
					corePoolSize, 
					maximumPoolSize,
					keepAliveTime, 
					unit, 
					workQueue
					);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
